import RequestWithUserId from "../../interface/requestWithUserId.if";
import HttpException from "../../exception/http.ex";
import BadRequestException from "../../exception/badRequest.ex";
import express, { NextFunction, Router } from "express";
import Controller from "../../interface/controller.if";

import postModel from "./post.model";
import validationMiddleware from "../../middleware/validation.mw";
import CreatePostDto from "./post.create.dto";
import authMiddleware from "../../middleware/auth.mw";
import AuthenticationMissingException from "../../exception/authenticationMissing.ex";
/**
 * 发帖功能的 控制器
 */
export default class PostController implements Controller {
  router: Router;
  /**
   * 路径只有一个getter
   */
  private routePath: string = "/post";
  private post = postModel;

  constructor() {
    this.router = Router();
    this.useRoutes();
  }

  private useRoutes = () => {
    this.router.get(this.routePath, this.findPosts);
    this.router.get(`${this.routePath}/:id`, this.findById);

    this.router
      .all(`${this.routePath}/*`, authMiddleware)
      .delete(`${this.routePath}/:id`, this.deletePost)
      .patch(
        `${this.routePath}/:id`,
        validationMiddleware(CreatePostDto, true),
        this.modifyPost
      )
      .post(
        this.routePath,
        authMiddleware,
        validationMiddleware(CreatePostDto),
        this.createPost
      );
  };

  /**需要 token 鉴权 */
  private createPost = async (
    req: RequestWithUserId,
    res: express.Response,
    next: NextFunction
  ) => {
    try {
      const content = req.body;

      // 仅当鉴权成功 ,req对象中加入了_userId才能继续创建post
      if (req._userId) {
        const post = await this.post.create({
          ...content,
          author: req._userId,
        });

        if (post) {
          res.send(req.body);
        } else {
          next(new HttpException(500, "expected ERROR 创建post失败"));
        }
      }
      // 如果鉴权失败，req对象中没有_userId ，则认为验证信息缺失，不能创建(多余的逻辑，因为已经有authMw)
      else {
        next(new AuthenticationMissingException());
      }
    } catch (error) {
      console.log(error);

      next(new HttpException(500, "unexpected ERROR 创建post失败"));
    }
  };

  private findPosts = async (
    req: express.Request,
    res: express.Response,
    next: NextFunction
  ) => {
    const posts = await this.post.find();

    if (posts) {
      res.send(posts);
    } else {
      next(new HttpException(500));
    }
  };

  private findById = async (
    req: express.Request,
    res: express.Response,
    next: NextFunction
  ) => {
    try {
      const id = req.params.id;
      const post = await this.post.findById(id);
      res.send(post);
    } catch (error) {
      next(error);
    }
  };
  /**需要 token 鉴权 */
  private modifyPost = async (
    req: express.Request,
    res: express.Response,
    next: express.NextFunction
  ) => {
    const id = req.params.id;
    const newPost = req.body;
    if (id === undefined || newPost === undefined) {
      next(new HttpException(400, "badrequest"));
    } else {
      this.post
        .findByIdAndUpdate(id, newPost, { new: true })
        .then((post) => {
          res.send(post);
        })
        .catch((err) => {
          next(err);
        });
    }
  };
  /**需要 token 鉴权 */
  private deletePost = async (
    req: express.Request,
    res: express.Response,
    next: express.NextFunction
  ) => {
    const id = req.params.id;
    if (id === undefined) {
      next(new BadRequestException());
    } else {
      this.post
        .findByIdAndDelete(id)
        .then((successResponse) => {
          if (successResponse) {
            res.send(200);
          } else {
            res.send(404);
          }
        })
        .catch((err) => {
          next(new HttpException());
        });
    }
  };

  get path() {
    return this.routePath;
  }
}
